{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "W_tvPdyfA-BL"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "cellView": "form",
        "colab": {},
        "colab_type": "code",
        "id": "0O_LFhwSBCjm"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "9-3Pry4jh1-E"
      },
      "source": [
        "\u003ctable class=\"tfo-notebook-buttons\" align=\"left\"\u003e\n",
        "  \u003ctd\u003e\n",
        "    \u003ca target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/examples/blob/master/courses/udacity_intro_to_tensorflow_for_deep_learning/l07c01_saving_and_loading_models.ipynb\"\u003e\u003cimg src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" /\u003eRun in Google Colab\u003c/a\u003e\n",
        "  \u003c/td\u003e\n",
        "  \u003ctd\u003e\n",
        "    \u003ca target=\"_blank\" href=\"https://github.com/tensorflow/examples/blob/master/courses/udacity_intro_to_tensorflow_for_deep_learning/l07c01_saving_and_loading_models.ipynb\"\u003e\u003cimg src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" /\u003eView source on GitHub\u003c/a\u003e\n",
        "  \u003c/td\u003e\n",
        "\u003c/table\u003e"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "NxjpzKTvg_dd"
      },
      "source": [
        "# Saving and Loading Models\n",
        "\n",
        "In this tutorial we will learn how we can take a trained model, save it, and then load it back to keep training it or use it to perform inference. In particular, we will use transfer learning to train a classifier to classify images of cats and dogs, just like we did in the previous lesson. We will then take our trained model and save it as an HDF5 file, which is the format used by Keras. We will then load this model, use it to perform predictions, and then continue to train the model. Finally, we will save our trained model as a TensorFlow SavedModel and then we will download it to a local disk, so that it can later be used for deployment in different platforms."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "crU-iluJIEzw"
      },
      "source": [
        "\n",
        "\n",
        "## Concepts that will be covered in this Colab\n",
        "\n",
        "1. Saving models in HDF5 format for Keras\n",
        "2. Saving models in the TensorFlow SavedModel format\n",
        "3. Loading models\n",
        "4. Download models to Local Disk\n",
        "\n",
        "Before starting this Colab, you should reset the Colab environment by selecting `Runtime -\u003e Reset all runtimes...` from menu above."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "7RVsYZLEpEWs"
      },
      "source": [
        "# Imports\n",
        "\n",
        "In this Colab we will use the TensorFlow 2.0 Beta version. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "TEBj4fbVsL5u"
      },
      "outputs": [],
      "source": [
        "try:\n",
        "  # Use the %tensorflow_version magic if in colab.\n",
        "  %tensorflow_version 2.x\n",
        "except Exception:\n",
        "  !pip install -q -U \"tensorflow-gpu==2.0.0rc0\" "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "e3BXzUGabcI9"
      },
      "outputs": [],
      "source": [
        "!pip install -q -U tensorflow_hub\n",
        "!pip install -q -U tensorflow_datasets"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "a28UtPNlizGI"
      },
      "source": [
        "Some normal imports we've seen before. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "Hj4tWLi9riAK"
      },
      "outputs": [],
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "OGNpmn43C0O6"
      },
      "outputs": [],
      "source": [
        "import time\n",
        "import numpy as np\n",
        "import matplotlib.pylab as plt\n",
        "\n",
        "tf.enable_v2_behavior()\n",
        "import tensorflow_hub as hub\n",
        "import tensorflow_datasets as tfds\n",
        "tfds.disable_progress_bar()\n",
        "\n",
        "from tensorflow.keras import layers"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "amfzqn1Oo7Om"
      },
      "source": [
        "# Part 1: Load the Cats vs. Dogs Dataset"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Z93vvAdGxDMD"
      },
      "source": [
        "We will use TensorFlow Datasets to load the Dogs vs Cats dataset. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "DrIUV3V0xDL_"
      },
      "outputs": [],
      "source": [
        "splits = tfds.Split.ALL.subsplit(weighted=(80, 20))\n",
        "\n",
        "splits, info = tfds.load('cats_vs_dogs', with_info=True, as_supervised=True, split = splits)\n",
        "\n",
        "(train_examples, validation_examples) = splits"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "mbgpD3E6gM2P"
      },
      "source": [
        "The images in the Dogs vs. Cats dataset are not all the same size. So, we need to reformat all images to the resolution expected by MobileNet (224, 224)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "we_ftzQxNf7e"
      },
      "outputs": [],
      "source": [
        "def format_image(image, label):\n",
        "  # `hub` image modules exepct their data normalized to the [0,1] range.\n",
        "  image = tf.image.resize(image, (IMAGE_RES, IMAGE_RES))/255.0\n",
        "  return  image, label\n",
        "\n",
        "num_examples = info.splits['train'].num_examples\n",
        "\n",
        "BATCH_SIZE = 32\n",
        "IMAGE_RES = 224\n",
        "\n",
        "train_batches      = train_examples.cache().shuffle(num_examples//4).map(format_image).batch(BATCH_SIZE).prefetch(1)\n",
        "validation_batches = validation_examples.cache().map(format_image).batch(BATCH_SIZE).prefetch(1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "JzV457OXreQP"
      },
      "source": [
        "# Part 2: Transfer Learning with TensorFlow Hub\n",
        "\n",
        "We will now use TensorFlow Hub to do Transfer Learning."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "5wB030nezBwI"
      },
      "outputs": [],
      "source": [
        "URL = \"https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/4\"\n",
        "feature_extractor = hub.KerasLayer(URL,\n",
        "                                   input_shape=(IMAGE_RES, IMAGE_RES,3))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "CtFmF7A5E4tk"
      },
      "source": [
        "Freeze the variables in the feature extractor layer, so that the training only modifies the final classifier layer."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "Jg5ar6rcE4H-"
      },
      "outputs": [],
      "source": [
        "feature_extractor.trainable = False"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "RPVeouTksO9q"
      },
      "source": [
        "## Attach a classification head\n",
        "\n",
        "Now wrap the hub layer in a `tf.keras.Sequential` model, and add a new classification layer."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "mGcY27fY1q3Q"
      },
      "outputs": [],
      "source": [
        "model = tf.keras.Sequential([\n",
        "  feature_extractor,\n",
        "  layers.Dense(2, activation='softmax')\n",
        "])\n",
        "\n",
        "model.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "OHbXQqIquFxQ"
      },
      "source": [
        "## Train the model\n",
        "\n",
        "We now train this model like any other, by first calling `compile` followed by `fit`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "3n0Wb9ylKd8R"
      },
      "outputs": [],
      "source": [
        "model.compile(\n",
        "  optimizer='adam', \n",
        "  loss=tf.losses.SparseCategoricalCrossentropy(),\n",
        "  metrics=['accuracy'])\n",
        "\n",
        "EPOCHS = 3\n",
        "history = model.fit(train_batches,\n",
        "                    epochs=EPOCHS,\n",
        "                    validation_data=validation_batches)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "kb__ZN8uFn-D"
      },
      "source": [
        "## Check the predictions\n",
        "\n",
        "Get the ordered list of class names."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "W_Zvg2i0fzJu"
      },
      "outputs": [],
      "source": [
        "class_names = np.array(info.features['label'].names)\n",
        "class_names"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "4Olg6MsNGJTL"
      },
      "source": [
        "Run an image batch through the model and convert the indices to class names."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "fCLVCpEjJ_VP"
      },
      "outputs": [],
      "source": [
        "image_batch, label_batch = next(iter(train_batches.take(1)))\n",
        "image_batch = image_batch.numpy()\n",
        "label_batch = label_batch.numpy()\n",
        "\n",
        "predicted_batch = model.predict(image_batch)\n",
        "predicted_batch = tf.squeeze(predicted_batch).numpy()\n",
        "predicted_ids = np.argmax(predicted_batch, axis=-1)\n",
        "predicted_class_names = class_names[predicted_ids]\n",
        "predicted_class_names"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "CkGbZxl9GZs-"
      },
      "source": [
        "Let's look at the true labels and predicted ones."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "nL9IhOmGI5dJ"
      },
      "outputs": [],
      "source": [
        "print(\"Labels: \", label_batch)\n",
        "print(\"Predicted labels: \", predicted_ids)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "wC_AYRJU9NQe"
      },
      "outputs": [],
      "source": [
        "plt.figure(figsize=(10,9))\n",
        "for n in range(30):\n",
        "  plt.subplot(6,5,n+1)\n",
        "  plt.imshow(image_batch[n])\n",
        "  color = \"blue\" if predicted_ids[n] == label_batch[n] else \"red\"\n",
        "  plt.title(predicted_class_names[n].title(), color=color)\n",
        "  plt.axis('off')\n",
        "_ = plt.suptitle(\"Model predictions (blue: correct, red: incorrect)\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "mmPQYQLx3cYq"
      },
      "source": [
        "# Part 3: Save as Keras `.h5` model\n",
        "\n",
        "Now that we've trained the model,  we can save it as an HDF5 file, which is the format used by Keras. Our HDF5 file will have the extension '.h5', and it's name will correpond to the current time stamp."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "tCnNWTkZ3Ckz"
      },
      "outputs": [],
      "source": [
        "t = time.time()\n",
        "\n",
        "export_path_keras = \"./{}.h5\".format(int(t))\n",
        "print(export_path_keras)\n",
        "\n",
        "model.save(export_path_keras)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "9tdJWVHmnKxJ"
      },
      "outputs": [],
      "source": [
        "!ls"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "JgqmH1WVUKli"
      },
      "source": [
        " You can later recreate the same model from this file, even if you no longer have access to the code that created the model.\n",
        "\n",
        "This file includes:\n",
        "\n",
        "- The model's architecture\n",
        "- The model's weight values (which were learned during training)\n",
        "- The model's training config (what you passed to `compile`), if any\n",
        "- The optimizer and its state, if any (this enables you to restart training where you left off)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "yXole25Z799G"
      },
      "source": [
        "# Part 4:  Load the Keras `.h5` Model\n",
        "\n",
        "We will now load the model we just saved into a new model called `reloaded`. We will need to provide the file path and the `custom_objects` parameter. This parameter tells keras how to load the `hub.KerasLayer` from the `feature_extractor` we used for transfer learning."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "Rx-z3Qwx5RnB"
      },
      "outputs": [],
      "source": [
        "reloaded = tf.keras.models.load_model(\n",
        "  export_path_keras, \n",
        "  # `custom_objects` tells keras how to load a `hub.KerasLayer`\n",
        "  custom_objects={'KerasLayer': hub.KerasLayer})\n",
        "\n",
        "reloaded.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "XxDl2vPkf2ST"
      },
      "source": [
        "We can check that the reloaded model and the previous model give the same result"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "MFljA-Hd85Tu"
      },
      "outputs": [],
      "source": [
        "result_batch = model.predict(image_batch)\n",
        "reloaded_result_batch = reloaded.predict(image_batch)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "YeCZUUJK9Svv"
      },
      "source": [
        "The differnece in output should be zero:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "S3p5-uD39PC1"
      },
      "outputs": [],
      "source": [
        "(abs(result_batch - reloaded_result_batch)).max()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "KqU79kKFo7S2"
      },
      "source": [
        "As we can see, the reult is 0.0, which indicates that both models made the same predictions on the same batch of images."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "nKunO4soA4Dm"
      },
      "source": [
        "# Keep Training\n",
        "\n",
        "Besides making predictions, we can also take our `reloaded` model and keep training it. To do this, you can just train the `realoaded` as usual, using the `.fit` method."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "NEv-fnHEAplx"
      },
      "outputs": [],
      "source": [
        "EPOCHS = 3\n",
        "history = reloaded.fit(train_batches,\n",
        "                    epochs=EPOCHS,\n",
        "                    validation_data=validation_batches)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "5OKoZaAHFH_s"
      },
      "source": [
        "# Part 5: Export as SavedModel\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "3V47IwQbFTYT"
      },
      "source": [
        "You can also export a whole model to the TensorFlow SavedModel format. SavedModel is a standalone serialization format for Tensorflow objects, supported by TensorFlow serving as well as TensorFlow implementations other than Python. A SavedModel contains a complete TensorFlow program, including weights and computation. It does not require the original model building code to run, which makes it useful for sharing or deploying (with TFLite, TensorFlow.js, TensorFlow Serving, or TFHub).\n",
        "\n",
        "The SavedModel files that were created contain:\n",
        "\n",
        "* A TensorFlow checkpoint containing the model weights.\n",
        "* A SavedModel proto containing the underlying Tensorflow graph. Separate graphs are saved for prediction (serving), train, and evaluation. If the model wasn't compiled before, then only the inference graph gets exported.\n",
        "* The model's architecture config, if available.\n",
        "\n",
        "\n",
        "Let's save our original `model` as a TensorFlow SavedModel. To do this we will use the `tf.saved_model.save()` function. This functions takes in the model we want to save and the path to the folder where we want to save our model. \n",
        "\n",
        "This function will create a folder where you will find an `assets` folder, a `variables` folder, and the `saved_model.pb` file. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "LtpeKMfoGXrj"
      },
      "outputs": [],
      "source": [
        "t = time.time()\n",
        "\n",
        "export_path_sm = \"./{}\".format(int(t))\n",
        "print(export_path_sm)\n",
        "\n",
        "tf.saved_model.save(model, export_path_sm)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "5h6B1wITlu-9"
      },
      "outputs": [],
      "source": [
        "!ls {export_path_sm}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ktpsqHxJPIQW"
      },
      "source": [
        "# Part 6: Load SavedModel"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "v0FDcCn9ncDb"
      },
      "source": [
        "Now, let's load our SavedModel and use it to make predictions. We use the `tf.saved_model.load()` function to load our SavedModels. The object returned by `tf.saved_model.load` is 100% independent of the code that created it."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "c7_PM7lofG2V"
      },
      "outputs": [],
      "source": [
        "reloaded_sm = tf.saved_model.load(export_path_sm)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "esEODdtM0kHB"
      },
      "source": [
        "Now, let's use the `reloaded_sm` (reloaded SavedModel) to make predictions on a batch of images."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "lpQldy_bm3Ty"
      },
      "outputs": [],
      "source": [
        "reload_sm_result_batch = reloaded_sm(image_batch, training=False).numpy()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "65upCyVN0u3Q"
      },
      "source": [
        "We can check that the reloaded SavedModel and the previous model give the same result."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "hoCwmkGznR_0"
      },
      "outputs": [],
      "source": [
        "(abs(result_batch - reload_sm_result_batch)).max()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "wxuETjjs01pL"
      },
      "source": [
        "As we can see, the reult is 0.0, which indicates that both models made the same predictions on the same batch of images."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "7Nom-ka0yuqB"
      },
      "source": [
        "# Part 7: Loading the SavedModel as a Keras Model\n",
        "\n",
        "The object returned by `tf.saved_model.load` is not a Keras object (i.e. doesn't have `.fit`, `.predict`, `.summary`, etc. methods). Therefore, you can't simply take your `reloaded_sm` model and keep training it by running `.fit`. To be able to get back a full keras model from the Tensorflow SavedModel format we must use the `tf.keras.models.load_model` function. This function will work the same as before, except now we pass the path to the folder containing our SavedModel."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "Vi1jaqh8yvt6"
      },
      "outputs": [],
      "source": [
        "# Clone the model to undo the `.compile`\n",
        "# This is a Workaround for a bug when keras loads a hub saved_model  \n",
        "model = tf.keras.models.clone_model(model)\n",
        "\n",
        "t = time.time()\n",
        "export_path_sm = \"./{}\".format(int(t))\n",
        "print(export_path_sm)\n",
        "tf.saved_model.save(model, export_path_sm)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "1VPE2_QQGmAP"
      },
      "outputs": [],
      "source": [
        "reload_sm_keras = tf.keras.models.load_model(\n",
        "  export_path_sm,\n",
        "  custom_objects={'KerasLayer': hub.KerasLayer})\n",
        "\n",
        "reload_sm_keras.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "thTbiHE72GL4"
      },
      "source": [
        "Now, let's use the `reloaded_sm)keras` (reloaded Keras model from our SavedModel) to make predictions on a batch of images."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "-0oCJrNLKdKj"
      },
      "outputs": [],
      "source": [
        "result_batch = model.predict(image_batch)\n",
        "reload_sm_keras_result_batch = reload_sm_keras.predict(image_batch)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "jUQaxzFj2Q8k"
      },
      "source": [
        "We can check that the reloaded Keras model and the previous model give the same result."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "DJCD9JJxKg9F"
      },
      "outputs": [],
      "source": [
        "(abs(result_batch - reload_sm_keras_result_batch)).max()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "NFa6jNc4PW9F"
      },
      "source": [
        "# Part 8:  Download your model"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "2W_y1qMVQeCm"
      },
      "source": [
        "You can download the SavedModel to your local disk by creating a zip file. We wil use the `-r` (recursice) option to zip all subfolders. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "WPRFoU1xPCGF"
      },
      "outputs": [],
      "source": [
        "!zip -r model.zip {export_path_sm}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "MBZL85RsQBTj"
      },
      "source": [
        "The zip file is saved in the current working directory. You can see what the current working directory is by running:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "ALP-DfwSQRL8"
      },
      "outputs": [],
      "source": [
        "!ls"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "IR89aU-SRmsL"
      },
      "source": [
        "Once the file is zipped, you can download  it to your local disk. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "lOXYrlDkNjKQ"
      },
      "outputs": [],
      "source": [
        "try:\n",
        "  from google.colab import files\n",
        "  files.download('./model.zip')\n",
        "except ImportError:\n",
        "  pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "RzLutxq_SeLQ"
      },
      "source": [
        "The `files.download` command will  search for files in your current working directory. If the file you want to download is in a directory other than the current working directory, you have to include the path to the directory where the file is located."
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "collapsed_sections": [],
      "last_runtime": {
        "build_target": "",
        "kind": "local"
      },
      "machine_shape": "hm",
      "name": "l07c01_saving_and_loading_models.ipynb",
      "private_outputs": true,
      "provenance": [
        {
          "file_id": "1oi5M2-vtbn1hi_MyWtAxrEBxjt1E5ObZ",
          "timestamp": 1567723796062
        },
        {
          "file_id": "https://github.com/tensorflow/examples/blob/master/courses/udacity_intro_to_tensorflow_for_deep_learning/l06c01_tensorflow_hub_and_transfer_learning.ipynb",
          "timestamp": 1560309715338
        }
      ],
      "toc_visible": true,
      "version": "0.3.2"
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
